home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Utilities / Installers / Smaller Installer 2.0.1 / Preinstalled version / Examples / Hook Procedure Examples / PersonalizeHook / PersonalizeHook.c next >
Encoding:
C/C++ Source or Header  |  1996-07-26  |  10.9 KB  |  365 lines  |  [TEXT/CWIE]

  1. /******************************************************************************
  2.     Smaller Installer © 1996 Bill Goodman, All Rights Reserved
  3. *******************************************************************************
  4.  
  5. Personalize Hook Example
  6.  
  7. This installer hook procedure prompts the user to enter a name and organization
  8. string which is used to personalize the installed application. These strings
  9. are stored in an STR# resource (ID:1000) in the installed application. The user
  10. name is string #1 and the organization name is string #2. The strings are also
  11. saved in an "info" file on the installer startup disk so that subsequent
  12. installations will use the same personalization info.
  13.  
  14. To build this hook procedure, compile this code and create a code resource
  15. (Type:SICR, ID:501, non-preloaded, nonpurgeable, unlocked, unprotected,
  16. non-sysheap). Add this resource to the "PersonalizeHook.rsrc" file. Copy all
  17. the resources in "PersonalizeHook.rsrc" to your installer's resource file.
  18.  
  19. Set string #1 in the STR#:500 resource to specify the name of the application
  20. to be personalized.
  21.  
  22. Copy the "Volume Info" file to the distribution disk containing the installer.
  23. This file must contain 512 bytes of data (preferably random in appearance).
  24. The first byte must be 0xFF. This file may be invisible if desired.
  25.  
  26. Add an STR#:1000 resource to your application. The hook will modify the values
  27. in this resource after the application is installed. Add whatever code is
  28. appropriate to display these personalization strings in your application.
  29.  
  30. ******************************************************************************/
  31.  
  32. // This file is compatible with version 2.1 of the universal headers
  33. #include <Dialogs.h>
  34. #include <Files.h>
  35. #include <GestaltEqu.h>
  36. #include <LowMem.h>
  37. #include <SegLoad.h>
  38. #include <TextUtils.h>
  39.  
  40. #ifdef __MWERKS__
  41. #include <A4Stuff.h>
  42. #endif
  43.  
  44. #ifdef THINK_C
  45. #include <SetUpA4.h>
  46. #endif
  47.  
  48. #include "SIHookProc.h"
  49.  
  50.  
  51. /******************************************************************************
  52.     Function Prototypes
  53. ******************************************************************************/
  54. void AfterItemFunction(void);
  55. void FirstFunction(void);
  56.  
  57.  
  58. /******************************************************************************
  59.     Constant Definitions
  60. ******************************************************************************/
  61. // Dialog Definitions
  62. #define nameDlg                500    // Name and organization entry dialog
  63. #define ok_nameDlg            1        // OK button
  64. #define name_nameDlg            3        // Name edit text item
  65. #define org_nameDlg            4        // Organization edit text item
  66.  
  67. // Alert Definitions
  68. #define damagedAlrt            501    // "The installer disk is damaged. Please be sure you are using the original installer disk."
  69. #define nameErrAlrt            502    // "Please enter your name AND your organization's name."
  70. #define lockedAlrt            503    // "The installer disk is locked. Please unlock it and try again."
  71. #define installAlrt            504    // "An error occurred during installation. Please remove all files and try again."
  72.  
  73. // Indexed String Definitions
  74. #define filenameID            500    // Filename string
  75. #define personalizeID        1000    // Personalization resource
  76.  
  77.  
  78. /******************************************************************************
  79.     Variable Definitions
  80. ******************************************************************************/
  81. SIHookParmBlk *gParms;                        // Global pointer to parameter block
  82. Str31 infoFilename = "\pVolume Info";    // Name of info file
  83. Str255 gAppFilename;                            // Application filename
  84. Str255 gUserName;                                // User name string
  85. Str255 gUserOrg;                                // User organization string
  86.  
  87.  
  88. /*****************************************************************************/
  89. pascal void main(
  90.         SIHookParmBlk *parmBlk    // Pointer to parameter block
  91.         )
  92. /******************************************************************************
  93.     This is the main entry point for the installer hook procedure.
  94. ******************************************************************************/
  95. {
  96. #ifdef __MWERKS__
  97. long holdA4;
  98. #endif
  99.  
  100. // Set up access to global variables
  101. #ifdef THINK_C
  102. RememberA0();
  103. SetUpA4();
  104. #endif
  105.  
  106. #ifdef __MWERKS__
  107. holdA4 = SetCurrentA4();
  108. #endif
  109.  
  110. gParms = parmBlk;
  111.  
  112. switch (gParms->function)
  113.     {
  114.     case siHookFirst:
  115.         FirstFunction();
  116.         break;
  117.  
  118.     case siHookAfterItem:
  119.         AfterItemFunction();
  120.         break;
  121.     }
  122.  
  123. // Restore original A4 value
  124. #ifdef THINK_C
  125. RestoreA4();
  126. #endif
  127.  
  128. #ifdef __MWERKS__
  129. SetA4(holdA4);
  130. #endif
  131. }
  132.  
  133.  
  134. /*****************************************************************************/
  135. void FirstFunction(void)
  136. /******************************************************************************
  137.     Input parameters:
  138.         "targetVRefNum"    Volume reference number of target volume
  139.         "groupAPFlags"        Groups currently selected
  140.         "groupQUSel"
  141.         "groupVZSel"
  142.         "group32Flags"
  143.         "group64Flags"
  144.         "group96Flags"
  145.         "groupEnvironFlags"
  146.  
  147.     Returns:
  148.         "groupAPFlags"        Updated installation groups
  149.         "groupQUSel"
  150.         "groupVZSel"
  151.         "group32Flags"
  152.         "group64Flags"
  153.         "group96Flags"
  154.         "result"                Hook result code (siHookNoErr, siHookQuit)
  155.  
  156.     This function is called once when the installer is launched.
  157. ******************************************************************************/
  158. {
  159. OSErr error;
  160. short infoPathNum = 0;
  161. long rwCnt;
  162. short index;
  163. DialogPtr dlgPtr;
  164. short item;
  165. short tmpType;
  166. Handle tmpHdl;
  167. Rect tmpRect;
  168.  
  169. // Copy application name from resource into global string to speed up compares
  170. GetIndString(gAppFilename, filenameID, 1);
  171. if (gAppFilename[0] == 0)
  172.     goto FatalError;
  173.  
  174. // Open the info file
  175. error = HOpen(-LMGetSFSaveDisk(), fsRtDirID, infoFilename, fsCurPerm, &infoPathNum);
  176. if (error != noErr)
  177.     goto InfoError;
  178.  
  179. // Read the user name string
  180. rwCnt = 256;
  181. error = FSRead(infoPathNum, &rwCnt, gUserName);
  182. if (error != noErr)
  183.     goto InfoError;
  184.  
  185. // Read the user organization string
  186. rwCnt = 256;
  187. error = FSRead(infoPathNum, &rwCnt, gUserOrg);
  188. if (error != noErr)
  189.     goto InfoError;
  190.  
  191. if (gUserName[0] == 0xFF)
  192.     {    // Personalization strings have not been specified - prompt user to enter
  193.     dlgPtr = GetNewDialog(nameDlg, NULL, (WindowPtr) -1L);
  194.     if (dlgPtr == NULL)
  195.         goto FatalError;
  196.     for (;;)
  197.         {
  198.         ModalDialog(NULL, &item);
  199.         if (item != ok_nameDlg)
  200.             goto Terminate;    // User cancelled dialog
  201.     
  202.         // Read strings from dialog
  203.         GetDialogItem(dlgPtr, name_nameDlg, &tmpType, &tmpHdl, &tmpRect);
  204.         GetDialogItemText(tmpHdl, gUserName);
  205.         GetDialogItem(dlgPtr, org_nameDlg, &tmpType, &tmpHdl, &tmpRect);
  206.         GetDialogItemText(tmpHdl, gUserOrg);
  207.     
  208.         // Validate strings
  209.         if ((gUserName[0] != 0) && (gUserOrg[0] != 0))
  210.             break;
  211.     
  212.         CautionAlert(nameErrAlrt, NULL);    // "Entries are invalid"
  213.         }
  214.     DisposeDialog(dlgPtr);
  215.  
  216.     // Complement the characters in the name and organization strings to disguise them
  217.     for (index = 256; --index >= 0;)
  218.         gUserName[index] = ~gUserName[index];
  219.     
  220.     for (index = 256; --index >= 0;)
  221.         gUserOrg[index] = ~gUserOrg[index];
  222.     
  223.     // Save the strings in the info file
  224.     error = SetFPos(infoPathNum, fsFromStart, 0);
  225.     if (error != noErr)
  226.         goto InfoError;
  227.     
  228.     rwCnt = 256;
  229.     error = FSWrite(infoPathNum, &rwCnt, gUserName);
  230.     if (error != noErr)
  231.         goto InfoError;
  232.     
  233.     rwCnt = 256;
  234.     error = FSWrite(infoPathNum, &rwCnt, gUserOrg);
  235.     if (error != noErr)
  236.         goto InfoError;
  237.     }
  238.  
  239. // Complement the characters in the name and organization strings to
  240. // return the strings to normal format
  241. for (index = 256; --index >= 0;)
  242.     gUserName[index] = ~gUserName[index];
  243.  
  244. for (index = 256; --index >= 0;)
  245.     gUserOrg[index] = ~gUserOrg[index];
  246.  
  247. error = FSClose(infoPathNum);
  248. infoPathNum = 0;
  249. if (error != noErr)
  250.     goto InfoError;
  251. return;    // Good completion
  252.  
  253. ///// Error exits /////
  254.  
  255. // Error occured while accessing the info file
  256. InfoError:
  257. if ((error == vLckdErr) || (error == wPrErr))
  258.     StopAlert(lockedAlrt, NULL);    // "Volume is locked"
  259. else
  260.     StopAlert(damagedAlrt, NULL);    // "Disk is damaged"
  261. goto Terminate;
  262.  
  263. // Fatal error occurred
  264. FatalError:
  265. SysBeep(1);
  266.  
  267. // Cleanup and terminate
  268. Terminate:
  269. if (infoPathNum)
  270.     FSClose(infoPathNum);
  271. gParms->result = siHookQuit;    // Force installer to quit
  272. }
  273.  
  274.  
  275. /*****************************************************************************/
  276. void AfterItemFunction(void)
  277. /******************************************************************************
  278.     Input parameters:
  279.         "targetVRefNum"    Volume reference number of target volume
  280.         "groupAPFlags"        Groups currently selected
  281.         "groupQUSel"
  282.         "groupVZSel"
  283.         "group32Flags"
  284.         "group64Flags"
  285.         "group96Flags"
  286.         "groupEnvironFlags"
  287.         "filesRemaining"    Number of files remaining to install or remove
  288.         "bytesRemaining"    Number of bytes of data remaining to install or remove
  289.         "doingRemove"        Non-zero if doing remove operation
  290.         "anyItemsSkipped"    Non-zero if any item has been skipped during operation
  291.         "itemWasSkipped"    Non-zero if this item was skipped
  292.         "desVRefNum"        Volume reference number of destination volume
  293.         "desDirID"            Directory ID of destination directory
  294.         "itemName"            Name of item that was installed or removed
  295.         "itemIsFolder"        Non-zero if item is a folder
  296.         "fileType"            File type (files only)
  297.         "fileCreator"        File creator (files only)
  298.         "createDate"        Creation date (files only)
  299.         "lastModDate"        Last modification date (files only)
  300.         "rsrcForkLen"        Length of resource fork (files only)
  301.         "dataForkLen"        Length of data fork (files only)
  302.         "itemInfo"            Reference passed from BeforeItem call
  303.  
  304.     Returns:
  305.         "result"                Hook result code (siHookNoErr, siHookQuit, siHookAbort)
  306.  
  307.     This function is called after each item is installed or removed.
  308. ******************************************************************************/
  309. {
  310. short applResFileNum = -1;
  311. Handle resHdl;
  312. long resSize;
  313. Byte buf[514];
  314.  
  315. if (gParms->doingRemove)
  316.     return;    // No action required during remove operations
  317.  
  318. if (gParms->itemWasSkipped)
  319.     return;    // No action required if item was skipped
  320.  
  321. // Check to see if this item is the application file to customize
  322. if (!EqualString(gParms->itemName, gAppFilename, true, true))
  323.     return;    // Names do not match - no action required
  324.  
  325. // Build the personalization resource
  326. buf[0] = 0;
  327. buf[1] = 2;
  328. BlockMove(gUserName, &buf[2], (short) gUserName[0] + 1);
  329. BlockMove(gUserOrg, &buf[(short) gUserName[0] + 3], (short) gUserOrg[0] + 1);
  330.  
  331. // Open the installed application file
  332. SetResLoad(false);    // Prevent loading of resources with preload attribute
  333. applResFileNum = HOpenResFile(gParms->desVRefNum, gParms->desDirID, gParms->itemName, fsRdWrPerm);
  334. SetResLoad(true);
  335. if (applResFileNum == -1)
  336.     goto Fail;
  337.  
  338. // Update the personalization resource in the installed application file
  339. resHdl = Get1Resource('STR#', personalizeID);
  340. if (resHdl == 0)
  341.     goto Fail;
  342. resSize = (long) gUserName[0] + (long) gUserOrg[0] + 4;
  343. ReallocateHandle(resHdl, resSize);
  344. if (MemError() != noErr)
  345.     goto Fail;
  346. BlockMove(buf, *resHdl, resSize);
  347. ChangedResource(resHdl);
  348. if (ResError() != noErr)
  349.     goto Fail;
  350. WriteResource(resHdl);
  351. if (ResError() != noErr)
  352.     goto Fail;
  353. CloseResFile(applResFileNum);
  354. if (ResError() != noErr)
  355.     goto Fail;
  356. return;    // Note that it is not necessary to set the result if no error
  357.  
  358. // Error occurred during update
  359. Fail:
  360. if (applResFileNum != -1)
  361.     CloseResFile(applResFileNum);
  362. StopAlert(installAlrt, NULL);
  363. gParms->result = siHookAbort;
  364. }
  365.